#include "lua.h"
#include "lauxlib.h"
#include "ip2region.h"
//memory
static int memory_search(lua_State *L){
	uint_t ip;
	ip2region_entry *ip2rEntry;
	datablock_entry datablock;
	memset(&datablock, 0x00, sizeof(datablock_entry));

	ip2rEntry = (ip2region_entry*)luaL_checkudata(L, 1, "gge_ip2region");
	ip = luaL_checkint(L,2);

	ip2region_memory_search(ip2rEntry,ip,&datablock);
	lua_pushstring(L,datablock.region);
	lua_pushinteger(L,datablock.city_id);
	return 2;
}
static int memory_search_string(lua_State *L)
{
	char *ip;
	ip2region_entry *ip2rEntry;
	datablock_entry datablock;
	memset(&datablock, 0x00, sizeof(datablock_entry));

	ip2rEntry = (ip2region_entry*)luaL_checkudata(L, 1, "gge_ip2region");
	ip = (char *)luaL_checkstring(L,2);

	ip2region_memory_search_string(ip2rEntry,ip,&datablock);
	lua_pushstring(L,datablock.region);
	lua_pushinteger(L,datablock.city_id);
	return 2;
}
//binary
static int binary_search(lua_State *L){
	uint_t ip;
	ip2region_entry *ip2rEntry;
	datablock_entry datablock;
	memset(&datablock, 0x00, sizeof(datablock_entry));

	ip2rEntry = (ip2region_entry*)luaL_checkudata(L, 1, "gge_ip2region");
	ip = luaL_checkint(L,2);

	ip2region_binary_search(ip2rEntry,ip,&datablock);
	lua_pushstring(L,datablock.region);
	lua_pushinteger(L,datablock.city_id);
	return 2;
}
static int binary_search_string(lua_State *L)
{
	char *ip;
	ip2region_entry *ip2rEntry;
	datablock_entry datablock;
	memset(&datablock, 0x00, sizeof(datablock_entry));

	ip2rEntry = (ip2region_entry*)luaL_checkudata(L, 1, "gge_ip2region");
	ip = (char *)luaL_checkstring(L,2);

	ip2region_binary_search_string(ip2rEntry,ip,&datablock);
	lua_pushstring(L,datablock.region);
	lua_pushinteger(L,datablock.city_id);
	return 2;
}
//btree
static int btree_search(lua_State *L){
	uint_t ip;
	ip2region_entry *ip2rEntry;
	datablock_entry datablock;
	memset(&datablock, 0x00, sizeof(datablock_entry));

	ip2rEntry = (ip2region_entry*)luaL_checkudata(L, 1, "gge_ip2region");
	ip = luaL_checkint(L,2);

	ip2region_btree_search(ip2rEntry,ip,&datablock);
	lua_pushstring(L,datablock.region);
	lua_pushinteger(L,datablock.city_id);
	return 2;
}
static int btree_search_string(lua_State *L)
{
	char *ip;
	ip2region_entry *ip2rEntry;
	datablock_entry datablock;
	memset(&datablock, 0x00, sizeof(datablock_entry));
	
	ip2rEntry = (ip2region_entry*)luaL_checkudata(L, 1, "gge_ip2region");
	ip = (char *)luaL_checkstring(L,2);

	ip2region_btree_search_string(ip2rEntry,ip,&datablock);
	lua_pushstring(L,datablock.region);
	lua_pushinteger(L,datablock.city_id);
	return 2;
}
//
static int lua_create(lua_State *L)
{
	char *dbFile = (char *)luaL_checkstring(L,1);
	ip2region_entry* ip2rEntry = (ip2region_entry*)lua_newuserdata(L,sizeof(ip2region_entry));
	printf("%s\n",dbFile);
	if ( ip2region_create(ip2rEntry, dbFile)) {
		luaL_getmetatable(L, "gge_ip2region");
		lua_setmetatable(L, -2);
		return 1;
	}
	return 0;
}
static int lua_destroy(lua_State *L)
{
	ip2region_entry *ip2rEntry = (ip2region_entry*)luaL_checkudata(L, 1, "gge_ip2region");
	ip2region_destroy(ip2rEntry);
	return 0;
}

IP2R_API int luaopen_ip2region(lua_State* L)
{
	luaL_Reg methods[] = {
		{"memory_search", memory_search},
		{"memory_search_string", memory_search_string},
		{"binary_search", binary_search},
		{"binary_search_string", binary_search_string},
		{"btree_search", btree_search},
		{"btree_search_string", btree_search_string},
		{NULL, NULL},
	};
	luaL_newmetatable(L, "gge_ip2region");
	luaL_newlib(L, methods);
	lua_setfield(L, -2, "__index");
	lua_pushcfunction (L, lua_destroy);
	lua_setfield (L, -2, "__gc");
	lua_pop(L,1);

	lua_pushcfunction(L,lua_create);
	return 1;
}
